package concurrent1;

import java.util.LinkedList;
import java.util.Queue;
import java.util.concurrent.locks.ReentrantLock;
import java.util.concurrent.locks.Condition;

public class ReentrantLockDemo2 {
    private final ReentrantLock lock = new ReentrantLock();
    private final Condition notFull = lock.newCondition();
    private final Condition notEmpty = lock.newCondition();
    private final Queue<Integer> queue = new LinkedList<>();
    private final int capacity = 1;

    // 生产者方法
    public void produce(int value) throws InterruptedException {
        lock.lock();
        try {
            // 如果队列满了，等待notFull条件
            while (queue.size() == capacity) {
                System.out.println("Queue is full, producer waiting...");
//                System.out.println("");
                notFull.await();
            }
            queue.add(value);
            System.out.println("Produced: " + value);
            // 通知消费者队列不为空
            notEmpty.signal();
        } finally {
            System.out.println("Producer finally");
            lock.unlock();
        }
    }

    // 消费者方法
    public void consume() throws InterruptedException {
        lock.lock();
        try {
            // 如果队列为空，等待notEmpty条件
            while (queue.isEmpty()) {
                System.out.println("Queue is empty, consumer waiting...");
                notEmpty.await();
            }
            int value = queue.poll();
            System.out.println("Consumed: " + value);
            // 通知生产者队列不满
            notFull.signal();
        } finally {
            System.out.println("consume finally");
//            lock.unlock();
        }
    }

    public static void main(String[] args) {
        ReentrantLockDemo2 pc = new ReentrantLockDemo2();

        // 生产者线程
        Thread producer = new Thread(() -> {
            try {
                for (int i = 0; i < 10; i++) {
                    pc.produce(i);
                    Thread.sleep(100); // 模拟生产耗时
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        });

        // 消费者线程
        Thread consumer = new Thread(() -> {
            try {
                for (int i = 0; i < 10; i++) {
                    pc.consume();
                    Thread.sleep(150); // 模拟消费耗时
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        });

        producer.start();
        consumer.start();
    }
}